package com.woniu.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.entity.DeleteDTO;
import com.woniu.entity.TrainerDTO;
import com.woniu.pojo.Trainer;
import com.woniu.service.ITrainerService;
import com.woniu.util.PageData;
import com.woniu.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * <p>
 * 培训师 前端控制器
 * </p>
 *
 * @author xiaoruan
 * @since 2023-03-07
 */

/**
 * redis软件是多线程，但是它执行的时候是单线程，可以保证线程安全
 * 它单线程怎么保证效率呢
 * 因为它里面有多路复用，比如 医院的导诊台 按是否准备好了来确认优先级
 * */


@Api(tags = "培训师管理")
@RestController
@RequestMapping("/trainer")
public class TrainerController extends BaseController {

    /**
     * 上班大家用redisTemplate多点
     */
    @Resource
    RedisTemplate redisTemplate;

    @Autowired
    ITrainerService trainerService;

    @ApiOperation("查询全部")
    @GetMapping("/findAll")
    public Result getAll() {

        /**1.从redis中查询数据 range表示范围不会把数据弹出去，pope会将数据弹出去，然后就没数据了.0，-1表示查询全部*/
        List<Trainer> range = redisTemplate.opsForList().range("trainer:all", 0, -1);
        /**2.判断redis中是否存在数据，如果存在直接返回*/
        if (range != null && range.size() > 0) {
            return toDataResult(range);
        }
        /**3.redis中不存在数据则，查询数据库并将数据保存在redis中，然后返回查询结果*/

        List<Trainer> trainerlist = trainerService.list();
        //在redis中存储
        redisTemplate.opsForList().leftPushAll("trainer:all",trainerlist);

        return toDataResult(trainerlist);
    }

    /**
     * 用注解替换上面的方法
     * 一般只有热点数据，并且这个数据不会频繁改变才会存储到redis缓存中,所以一般是特定按条件查询出来的数据会用到、
     * redis中的数据其实还是存储在缓存中，但是可以持久化
     * 这边用注解演示一下，前端用到还是上面的这种方法
     * */
    @ApiOperation("查询全部2使用注解添加缓存")
    @GetMapping("/findAll/byService")
    public Result getAll2() {

        List<Trainer> trainerlist = trainerService.findAll();

        return toDataResult(trainerlist);
    }


    @ApiOperation("分页+条件")
    @PostMapping("/page/{currentPage}/{pageSize}")
    public Result getPage(@PathVariable Integer currentPage,
                          @PathVariable Integer pageSize,
                          @RequestBody TrainerDTO trainerDto) {
        //1.数据校验
        //2.调用方法，拿到返回值
        PageData pageData = trainerService.getPageData(currentPage, pageSize, trainerDto);
        //3.返回数据
        return toDataResult(pageData);

    }

    @Caching(evict = {
            @CacheEvict(value = "trainer:all",allEntries = true)
    })
    @ApiOperation("根据id删除")
    @DeleteMapping("/delete/{id}")
    public Result deleteTrainer(@PathVariable String id) {

        boolean b = trainerService.removeById(id);

        return toResult(b);
    }

    /**
     * 使用了redis后会先去查redis中找，但是如果我数据库删除了一条数据，缓存数据就不同步了
     * 所以得把redis中的数据同步,最简单就是清除缓存，
     * 注解或者调用方法
     * */
    @Caching(evict = {
            @CacheEvict(value = "trainer:all",allEntries = true)
    })
    @ApiOperation("批量删除1")
    @PostMapping("/delete")
    public Result delTrainers(@RequestBody List<String> ids) {
//         trainerService.delSel(ids);

        boolean b = trainerService.removeBatchByIds(ids);
        if (b){
            //清空相关的缓存 要不就用注解
            redisTemplate.delete("trainer:all");
        }

//        Arrays.stream(ids).sequential().forEach(e->{
//
//
//            trainerService.removeById(e);
//
//
//        });
        return toResult(b);

    }

    @Caching(evict = {
            @CacheEvict(value = "trainer:all",allEntries = true)
    })
    @ApiOperation("批量删除2")
    @PostMapping("/delete2")
    public Result delTrainersAndReturn(@RequestBody DeleteDTO deleteDTO) {

        Result b = trainerService.delBatch(deleteDTO);

        return b;

    }


    @ApiOperation("根据id查询")
    @GetMapping("/get/{id}")
    public Result getTrainerById(@PathVariable String id) {
        Trainer trainer = trainerService.getById(id);

        return toDataResult(trainer);
    }


    @ApiOperation("根据name查询")
    @GetMapping("/find/{name}")
    public Result getTrainerByName(@PathVariable String name) {


        QueryWrapper<Trainer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        Trainer trainer = trainerService.getOne(queryWrapper);

        return toDataResult(trainer);
    }


    @Caching(evict = {
            @CacheEvict(value = "trainer:all",allEntries = true)
    })
    @ApiOperation("新增")
    @PostMapping("/add")
    public Result addTrainer(@RequestBody Trainer trainer) {

        boolean save = trainerService.save(trainer);
        if (save){
            String avatar = trainer.getAvatar();
            String filename = avatar.substring(avatar.lastIndexOf("/")+1);
            redisTemplate.opsForSet().add("redis_db_upload_image",filename);
        }

        return toResult(save);
    }

    @Caching(evict = {
            @CacheEvict(value = "trainer:all",allEntries = true)
    })
    @ApiOperation("修改")
    @PutMapping("/update")
    public Result updateTrainer(@RequestBody Trainer trainer) {

        boolean update = trainerService.updateById(trainer);
        if (update){
            String avatar = trainer.getAvatar();
            String filename = avatar.substring(avatar.lastIndexOf("/")+1);
            redisTemplate.opsForSet().add("redis_db_upload_image",filename);
        }

        return toResult(update);
    }

    @Caching(evict = {
            @CacheEvict(value = "trainer:all",allEntries = true)
    })
    @ApiOperation("修改和新增")
    @PostMapping("/updateAndAdd")
    public Result updateAndAdd(@RequestBody Trainer trainer) {

        boolean update = trainerService.saveOrUpdate(trainer);
        //将用户的图片存储到redis的set集合中，这边哟啊用set去存
        if (update){
            String avatar = trainer.getAvatar();
            String filename = avatar.substring(avatar.lastIndexOf("/")+1);
            redisTemplate.opsForSet().add("redis_db_upload_image",filename);
        }


        return toResult(update);
    }

    @PostMapping("/export")
    public void export(@RequestBody TrainerDTO trainerDTO,HttpServletResponse response) throws IOException {
    //1.根据搜索条件查询数据
        PageData pageData = trainerService.getPageData(1, 1000000, trainerDTO);
    //2.将查询出来的数据通过eaxyExcel写到文件中
        EasyExcel.write(response.getOutputStream(),Trainer.class).sheet().doWrite((List<Trainer>) pageData.getData());


    }




}
